package com.xiaojie.importdata.handler;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xiaojie.context.DataInfoContext;
import com.xiaojie.parse.model.Settings;
import com.xiaojie.parse.model.Table;
import com.xiaojie.toolkits.FieldNameUtil;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * 替换表中字段值
 *
 * @Author: wangye
 * @Date: 2022/3/11 15:44
 * @return:
 **/
public abstract class AbstractReplaceFieldValueHandler implements ReplaceFieldValueHandler {

    /**
     * 获取配置文件中需要保留新旧数据对应关系的字段名称
     * 返回的集合中同一个字段名会存驼峰和下划线两种格式
     * 表中setting的配置优先于全局配置globalSettings
     *
     * @param tableSettings
     * @param globalSettings
     * @auther wangye
     * @date 2021/10/10
     */
    protected List<String> getCorrespondFieldNames(Settings tableSettings, Settings globalSettings) {
        List<String> fieldNameList = getCorrespondFieldNames(tableSettings);
        if (CollectionUtil.isEmpty(fieldNameList)) {
            return getCorrespondFieldNames(globalSettings);
        }
        return fieldNameList;
    }

    protected List<String> getCorrespondFieldNames(Settings settings) {
        if (settings == null)
            return Lists.newArrayList();
        List<String> list = Optional.ofNullable(settings.getCorrespondDataFields()).orElse(Lists.newArrayList());
        List<String> correspondDataFieldNameList = Lists.newArrayList();
        list.forEach(fieldName -> {
            correspondDataFieldNameList.add(FieldNameUtil.convert(fieldName));
        });
        return correspondDataFieldNameList;
    }

    /**
     * 保留被依赖字段的新旧值
     * 依赖分为（被其它表依赖）、（表中字段相互依赖）
     *
     * @param refFieldDataMap
     * @param tableName
     * @param oldValue
     * @param refFieldsMap
     * @param fieldName
     * @param newFieldValue
     * @Author: wangye
     * @Date: 2022/2/22 15:35
     * @return:
     **/
    protected void buildFieldRefDataMap(Map<String, Map<String, Map>> refFieldDataMap, String tableName, Object oldValue,
                                        Map<String, Set<String>> refFieldsMap, String fieldName, Object newFieldValue) {
        //replaceRefFieldValue方法里的参数refFieldDataMap是在这里设置的值
        //判断字段是否被关联，保留被依赖字段与旧值与新值得对应关系

        Table table = DataInfoContext.get().getDataModelInfo().getTables().get(tableName);

        Map<String, String> selfRelFields = table.getSelfRelFields();
        //当前字段是否被本表q其它字段关联
        boolean isSelfTableRefField = Optional.ofNullable(selfRelFields).map(m -> m.entrySet()
                .stream().map((Map.Entry<String, String> entry) -> entry.getValue())
                .anyMatch(refedFieldName -> fieldName.equals(refedFieldName))).orElse(false);
        //当前字段是否被其它表关联的字段
        boolean isOtherTableRefField = Optional.ofNullable(refFieldsMap.get(tableName))
                .map(fields -> fields.contains(fieldName))
                .orElse(false);

        if (isOtherTableRefField || isSelfTableRefField) {
            //获取对应表的关联数据
            Map<String, Map> refDataMap =
                    Optional.ofNullable(refFieldDataMap.get(tableName))
                            .orElse(Maps.newHashMap());

            //获取对应表的关联数据
            Map map =
                    Optional.ofNullable(refDataMap.get(fieldName))
                            .orElse(Maps.newHashMap());
            //设置关联表 新旧数据
            map.put(oldValue, newFieldValue);
            refDataMap.put(fieldName, map);
            refFieldDataMap.put(tableName, refDataMap);
        }
    }

}
